package classfile

/*
	这里表示字段与方法

	之所以需要名字和描述符，一个很重要的原因就是方法重载的问题（名字相同，参数个数，类型不同）
	这样可以通过描述符来区分

	虚拟机规定的字段信息
	field_info {
		u2 access_flags;
		u2 name_index; //名字在常量池中的索引
		u2 descriptor_index; //描述符在常量池中的索引
		u2 attributes_count; //属性表
		attribute_info attributes[attributes_count];
	}

	name_index和descriptor_index指向的其实是Constant_Utf8_info类型的常量信息

	descriptor（描述符）指的是jvm规范中定义的一种简单的语法来描述方法和字段
		比如byte，short，char，int，long，float，double的描述符是单个字母
		分别为B,S,C,I,J,F,D

		下面是一些方法描述符示例：括号内表示参数，括号外表示返回类型
			void run()，描述符为()V
			float max(float x,float y)，描述符为(FF)F
			int binarySearch(long[]a,long key) ([JJ)I
			String toString() 描述符为()Ljava.lang.String
		具体的详细信息，可以在虚拟机规范4.3节中查找


	虚拟机规定的方法信息

*/

/*
field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
*/

type MemberInfo struct {
	cp              ConstantPool
	accessFlags     uint16
	nameIndex       uint16
	descriptorIndex uint16
	attributes      []AttributeInfo
}

// read field or method table
func readMembers(reader *ClassReader, cp ConstantPool) []*MemberInfo {
	memberCount := reader.readUint16()
	members := make([]*MemberInfo, memberCount)
	for i := range members {
		members[i] = readMember(reader, cp)
	}
	return members
}

func readMember(reader *ClassReader, cp ConstantPool) *MemberInfo {
	return &MemberInfo{
		cp:              cp,
		accessFlags:     reader.readUint16(),
		nameIndex:       reader.readUint16(),
		descriptorIndex: reader.readUint16(),
		attributes:      readAttributes(reader, cp),
	}
}

func (self *MemberInfo) AccessFlags() uint16 {
	return self.accessFlags
}
func (self *MemberInfo) Name() string {
	return self.cp.getUtf8(self.nameIndex)
}
func (self *MemberInfo) Descriptor() string {
	return self.cp.getUtf8(self.descriptorIndex)
}
